package com.pokeoffice.tests;

import static org.junit.Assert.*;

import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

import org.junit.*;

import com.pokeoffice.client.Client;
import com.pokeoffice.commands.TestCommand;
import com.pokeoffice.commands.TestCommand2;
import com.pokeoffice.logs.TestLogger;
import com.pokeoffice.server.Server;

/**
 * The Class ServerClientTests.
 */
public class ServerClientTests {

	/** The s1. */
	static Server s1 = null;
	
	/** The s1t. */
	static Thread s1t = null;

	/** The c1. */
	static Client c1 = null;
	
	/** The c1t. */
	static Thread c1t = null;

	/** The c2. */
	static Client c2 = null;
	
	/** The c2t. */
	static Thread c2t = null;

	/** The DELAY. */
	int DELAY = 500;

	/**
	 * Sets the up.
	 */
	@Before
	public void SetUp() {
		long time;
		if (s1 == null) {
			s1 = new Server();
			s1t = new Thread(new Server());
			s1t.start();

			// 1 second to allow server time to start
			time = System.currentTimeMillis();
			while (System.currentTimeMillis() - time < DELAY) {
				;
			}
		}

		if (c1 == null) {
			c1 = new Client();
			c1t = new Thread(c1);
			c1t.start();

			// 1 second to allow clients time to start
			time = System.currentTimeMillis();
			while (System.currentTimeMillis() - time < DELAY) {
				;
			}
		}
		
		if (c2 == null) {
			c2 = new Client();
			c2t = new Thread(c2);
			c2t.start();


			// 1 second to allow clients time to start
			time = System.currentTimeMillis();
			while (System.currentTimeMillis() - time < DELAY) {
				;
			}
		}
	}

	/**
	 * Basic commands.
	 */
	@Test
	@Ignore
	public void BasicCommands() {
		String test = "BasicCommands";
		String file = "temp/" + test;
		int commands = 1000;

		try {
			TestLogger.write(TestLogger.STT, test, test);

			TestLogger.write(TestLogger.TXT, "EXPECTED: ", test);
			for (int i = 0; i < commands; i++) {
				TestLogger.write(TestLogger.TXT, "" + i + ":T ", test);
			}

			TestLogger.write(TestLogger.TXT, "\nACTUAL:   ", test);
			
			// Starts two clients and runs commands for testing purposes
			for (int i = 0; i < commands; i++) {
				if ((i&1) == 0) {
					c1.put(new TestCommand(i, file));
				} else {
					c2.put(new TestCommand(i, file));
				}
			}

			// Allows 1 millisecond for each command
			long time = System.currentTimeMillis();
			while (System.currentTimeMillis() - time < commands) {
				;
			}

			boolean[] results = new boolean[commands];
			Scanner sc = new Scanner(new File(file));
			while (sc.hasNext()) {
				int i = sc.nextInt();
				if (i < commands) {
					results[i] = true;
				}
			}

			for (int i = 0; i < commands; i++) {
				TestLogger.write(TestLogger.RES, "" + i + ":" + (results[i]? "T ":"F "), test);
			}

			PrintWriter pw = new PrintWriter(new File(file));
			pw.flush();
			pw.close();

			TestLogger.write(TestLogger.STP, test + " Completed", test);
		} catch (Exception e) {
			TestLogger.write(TestLogger.STP, test + " Failed", test);
			fail();
		}
	}

	/**
	 * Multiple command types.
	 */
	@Test
	@Ignore
	public void MultipleCommandTypes() {
		String test = "MultipleCommandTypes";
		String file = "temp/" + test;
		int commands = 1000;

		try {
			TestLogger.write(TestLogger.STT, test, test);

			ArrayList<Long> expected = new ArrayList<Long>();

			// Starts two clients and runs commands for testing purposes
			for (int i = 0; i < commands; i++) {
				if ((i&1) == 0) {
					c1.put(new TestCommand(i, file));
					expected.add((long) i);
				} else {
					c2.put(new TestCommand2(i, file));
					expected.add(Long.parseLong(i + "" + i));
				}
			}

			Collections.sort(expected);

			TestLogger.write(TestLogger.TXT, "EXPECTED: ", test);
			
			for (long l : expected) {
				TestLogger.write(TestLogger.TXT, l + " ", test);
			}

			TestLogger.write(TestLogger.TXT, "\nACTUAL:   ", test);

			// Allows 1 millisecond for each command
			long time = System.currentTimeMillis();
			while (System.currentTimeMillis() - time < commands) {
				;
			}

			ArrayList<Long> results = new ArrayList<Long>();
			Scanner sc = new Scanner(new File(file));
			while (sc.hasNext()) {
				long i = sc.nextLong();
				results.add(i);
			}


			Collections.sort(results);

			for (long l : results) {
				TestLogger.write(TestLogger.RES, l + " ", test);
			}

			PrintWriter pw = new PrintWriter(new File(file));
			pw.flush();
			pw.close();

			TestLogger.write(TestLogger.STP, test + " Completed", test);
		} catch (Exception e) {
			TestLogger.write(TestLogger.STP, test + " Failed", test);
			fail();
		}
	}
}
